

#include <chrono>
#include <cmath>
#include <execution>
#include <iostream>
#include <numeric>
#include <vector>

void f1(const std::vector<double>& vec)
{
    auto beg = std::chrono::high_resolution_clock::now();
    auto res = std::accumulate(vec.begin(), vec.end(), 0, [](double a, double b) {
        double x = std::sin(a) * std::cos(b); // 更重的计算
        return a + b + (double)x;
    });
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - beg);
    std::cout << "accumulate: " << res << ", cost: " << duration << std::endl;
}

void f2(const std::vector<double>& vec)
{
    auto beg = std::chrono::high_resolution_clock::now();
    auto res = std::reduce(std::execution::par, vec.begin(), vec.end(), 0, [](double a, double b) {
        double x = std::sin(a) * std::cos(b); // 更重的计算
        return a + b + (double)x;
    });
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - beg);
    std::cout << "reduce with std::execution::par: " << res << ", cost: " << duration << std::endl;
}

void f3(const std::vector<double>& vec)
{
    auto beg = std::chrono::high_resolution_clock::now();
    auto res = std::reduce(vec.begin(), vec.end(), 0, [](double a, double b) {
        double x = std::sin(a) * std::cos(b); // 更重的计算
        return a + b + (double)x;
    });
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - beg);
    std::cout << "reduce without std::execution::par: " << res << ", cost: " << duration << std::endl;
}

int main()
{
    std::vector<double> vec(100000000, 0.2);
    f1(vec);
    f2(vec);
    f3(vec);

    std::vector<double> v { 1.0, 2.0, 3.0 };
    double x1 = std::accumulate(v.begin(), v.end(), 0.0, std::minus<double>());
    std::cout << "x1: " << x1 << std::endl;
    // 满足交换律和结合律才能用reduce
    double x2 = std::reduce(v.begin(), v.end(), 0.0, std::minus<double>());
    std::cout << "x2: " << x2 << std::endl;

    return 0;
}